package com.epi.two;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.atomic.*;

/**
 * @author dxy
 * @version 1.0
 */
public class DateDemo {
    public static void main(String[] args) {
//        dataUtilDemo();
//        instanceDemo();
//        temporalAdjustDemo();
//        localAndZoneDemo();
//        zoneIdDemo();
//        zoneTime(Instant.now());
//        dstDemo();
//        dateTimeFormatterDemo();
    }

    private static void dateTimeFormatterDemo() {
        LocalDate date = LocalDate.of(2025, 6, 26);
        LocalTime time = LocalTime.of(14, 45, 30);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        ZonedDateTime zonedDateTime = ZonedDateTime.of(dateTime, ZoneId.of("Asia/Shanghai"));

        // 1. ✅ ISO 标准格式器（内置）
        System.out.println("=== ISO 标准格式器 ===");
        System.out.println("ISO_DATE:       " + date.format(DateTimeFormatter.ISO_DATE));
        System.out.println("ISO_TIME:       " + time.format(DateTimeFormatter.ISO_TIME));
        System.out.println("ISO_DATE_TIME:  " + dateTime.format(DateTimeFormatter.ISO_DATE_TIME));
        System.out.println("ISO_ZONED_DATE_TIME: " + zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));

        // 2. ✅ 本地化格式器 SHORT MEDIUM LONG FULL
        System.out.println("\n=== 本地化格式器 ===");
        DateTimeFormatter longCn = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.CHINA);
        DateTimeFormatter shortUs = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(Locale.US);
        System.out.println("中文全格式:      " + zonedDateTime.format(longCn));
        System.out.println("美国短格式:      " + zonedDateTime.format(shortUs));

        // 3. ✅ 自定义格式器
        System.out.println("\n=== 自定义格式器 ===");
        DateTimeFormatter custom = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss EEE MM MMM MMMM MMMMM");
        DateTimeFormatter custom2 = DateTimeFormatter.ofPattern("EEE, MMM d yyyy HH:mm", Locale.ENGLISH);
        System.out.println("自定义格式:      " + dateTime.format(custom));
        System.out.println("英文自定义:      " + dateTime.format(custom2));

        // 4. ✅ 解析字符串
        System.out.println("\n=== 解析字符串 ===");
        String input = "2025-06-26 14:45:30";
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parsedDateTime = LocalDateTime.parse(input, parser);
        System.out.println("解析结果:       " + parsedDateTime);

        // 5. ✅ 带时区格式化
        System.out.println("\n=== 带时区格式化 ===");
        DateTimeFormatter zoneFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z VV");
        System.out.println("带时区输出:     " + zonedDateTime.format(zoneFormatter));
    }

    private static void dstDemo() {
        // 设置一个在夏令时开始前的一天（美国 2024 年 3 月 9 日 12:00 中午）
        LocalDateTime localTime = LocalDateTime.of(2024, 3, 9, 12, 0);
        ZoneId zone = ZoneId.of("America/New_York");

        ZonedDateTime base = localTime.atZone(zone);
        System.out.println("原时间:       " + base);

        // 加上 Period 7 天（加7天，忽略夏令时）
        ZonedDateTime plusPeriod = base.plus(Period.ofDays(7));
        System.out.println("Period +7天: " + plusPeriod);

        // 加上 Duration 7天（加168小时，考虑夏令时）
        ZonedDateTime plusDuration = base.plus(Duration.ofDays(7));
        System.out.println("Duration +7天: " + plusDuration);
    }

    private static void zoneTime(Instant fromDb) {
        System.out.println(ZonedDateTime.now());
        System.out.println(ZonedDateTime.now(ZoneId.of("America/New_York")));
        System.out.println(ZonedDateTime.now(Clock.systemUTC()));

        System.out.println(OffsetDateTime.now());
        System.out.println(OffsetDateTime.now(ZoneId.of("America/New_York")));
        System.out.println(OffsetDateTime.now(Clock.systemUTC()));

        ZonedDateTime sydney = ZonedDateTime.ofInstant(fromDb, ZoneId.of("Australia/Sydney"));
        ZonedDateTime beijing = ZonedDateTime.ofInstant(fromDb, ZoneId.systemDefault());
        System.out.println(sydney.format(DateTimeFormatter.ofPattern("dd-MM-yy HH:mm:ss")));
        System.out.println(beijing.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }

    private static void zoneIdDemo() {
        AtomicInteger index = new AtomicInteger(1);
        ZoneId.getAvailableZoneIds().stream()
            .sorted()
            .forEach(zoneId -> System.out.println(index.getAndIncrement() + ": " + zoneId));
    }

    private static void localAndZoneDemo() {
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.now();
//        合成 LocalDateTime
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        ZonedDateTime zonedDateTime = dateTime.atZone(ZoneId.of("America/Los_Angeles"));

        System.out.println(dateTime);
        System.out.println(zonedDateTime);
    }

    private static void temporalAdjustDemo() {
        LocalDate today = LocalDate.now();
        LocalDate firstDay = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDay = today.with(TemporalAdjusters.lastDayOfMonth());
        LocalDate monDay = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));

        System.out.println("First Day: " + firstDay);
        System.out.println("Last Day: " + lastDay);
        System.out.println("MonDay: " + monDay);
    }

    private static void instanceDemo() {
        LocalDateTime startTime = LocalDateTime.of(2000, 1, 1, 1, 1, 1);
        Instant startInstant = startTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant();
        Instant endInstance = Instant.now();
        Duration duration = Duration.between(startInstant, endInstance);
        System.out.println(duration.toMillis());
    }

    private static void dataUtilDemo() {
        LocalDate start = LocalDate.of(2000, 1, 1);
        LocalDate now = LocalDate.now();
        start.datesUntil(now, Period.ofYears(2)).forEach(System.out::println);
    }
}
